#include "folder.h"

// le constructeur prend en parametres le nom du repertoire et sa profondeur
// i.e. le nombre de repertoires qu'il faut remonter pour revenir à la racine
Folder::Folder(char* nomRep, int p) {
	/* exemple de nomRep : "/usr/lib/blabla/"	*/
	name = nomRep;
	prof = p;
	size = 0;
	fileCount = 0;
	repCount = 0;
	objCount = 0;
	files = new vector<File*>;
	subfolders = new vector<Folder*>;
	rep = opendir(name); // ouverture du repertoire
	while ((element = readdir(rep))) // tant qu'il y a des elts dans le rep
	{
		// si les elts courants ne sont ni . ni ..
		if (strcmp(element->d_name,".") && strcmp(element->d_name,".."))
		{
			if (element->d_type == DT_REG) // si elt courant : fichier
			{
				// on concatene le chemin et le nom du fichier
				char *temp = new char[256];
				sprintf(temp,"%s%s",name,element->d_name);
				// on rajoute un objet de type File correspondant
				File::File *fic = new File(temp);	
				(*files).push_back(fic);
				// on met à jour la taille du dossier 
				size = size + fic->getSize();
				// et le nombre de fichiers total			
				fileCount++;
			}
			else if (element->d_type == DT_DIR) // si elt courant : repertoire
			{
				// on concatene le chemin et le nom du repertoire	
				char *temp = new char[256];
				sprintf(temp,"%s%s/",name,element->d_name);
				// on rajoute un objet de type Folder correspondant
				// avec une profondeur incrémentée de 1
				Folder::Folder *fold = new Folder(temp,prof+1);
				(*subfolders).push_back(fold);
				// on rajoute la taille du dossier fils
				size = size + fold->getSize();
				// et on incrémente le nombre de sous-répertoires
				repCount++;
			}
			// nombre d'objets : utilisé à des fins d'affichage
			objCount++;
		}
	}
	// printf("\nnb de fichiers sur %s : %d\n",nomRep,fileCount);	
	// printf("nb de rep sur %s : %d\n",nomRep,repCount);	
	// printf("nb d'objets sur %s : %d\n\n",nomRep,objCount);
	closedir(rep);	
	// cout << "first fic " << (*((*files)[0])).name << endl;	
	// if ((*subfolders).size() > 0)	
	//	cout << "first rep " << (*((*subfolders)[0])).name << endl;	
	/* lire les dates de création et modif depuis le
	repertoire ext3 : plus tard */

	// flag pour voir si le noeud est terminal
	estTerminal = false;
	if (((*files).size() == 0) && ((*subfolders).size() == 0))
		estTerminal = true;

	// flag pour voir si le noeud n'a que des fils terminaux
	// i.e. on va afficher ses fils (algo de parcours en prof)
	queDesFilsTerminaux = true;
	for (size_t i=0; i<(*subfolders).size(); i++)
		if (((*subfolders)[i])->estTerminal == false)
			queDesFilsTerminaux = false;

	cout << endl;
	vector<File*> *files_right = new vector<File*>; 
	*files_right = getRightFiles();
	vector<File*> *files_left = new vector<File*>;
	*files_left = getLeftFiles();
	vector<Folder*> *sub_ord = new vector<Folder*>;
	*sub_ord = getOrderedSubfolders();
	for (size_t i=0; i<(*files_left).size(); i++)
		cout << "fichier gauche " << i << " : " << ((*files_left)[i])->name << endl;
	for (size_t i=0; i<(*sub_ord).size(); i++)
		cout << "rep " << i << " : " << ((*sub_ord)[i])->name << "prof : " << ((*sub_ord)[i])->getProfMax() << endl;
	for (size_t i=0; i<(*files_right).size(); i++)
		cout << "fichier droite " << i << " : " << ((*files_right)[i])->name << endl;

}

char* Folder::getNom() {
	return name;
}

long Folder::getSize() {
	return size;
}

vector<File*> Folder::getFiles() {
	return *files;
}

// vector<Folder*> Folder::getSubfolders() {
// 	return *subfolders;
//}

File* Folder::getFileNo(size_t i) {
	return ((*files)[i]);
} 

Folder* Folder::getFolderNo(size_t i) {
	return ((*subfolders)[i]);
}

int Folder::getProfondeur() {
	return prof;
}

// renvoie la profondeur max à partir du rep courant
int Folder::getProfMax() {
	int pmax=getProfondeur();
	for (size_t i=0; i<(*subfolders).size(); i++)
	{
			int p=((*subfolders)[i])->getProfMax();
			if (p > pmax)
				pmax = p;
	}
	return pmax;	
}

int Folder::getNbObjets() {
	return objCount;
}

// renvoie le nombre de fils max qu'un fils peut avoir
int Folder::getNbObjetsMax() {
	int nbobjmax=objCount;
	for (size_t i=0; i<(*subfolders).size(); i++)
	{
			int n=((*subfolders)[i])->getNbObjetsMax();
			if (n > nbobjmax)
				nbobjmax = n;
	}
	return nbobjmax;		
}

// fonctions d'affichage 
// pour chaque noeud dont on veut afficher les fils, on reorganise
// les objets : fichiers sur les côtés et repertoires de plus
// grande profondeur au milieu pour maintenir un arbre "droit"

// renvoie les fichiers a afficher a gauche des repertoires
vector<File*> Folder::getLeftFiles() {
	// n : le nombre de fichiers
	size_t n = (*files).size();
	vector<File*> *files_left;
	files_left = new vector<File*>;
	// si n est pair on prend les n/2 premiers fichiers	
	if ( n%2 == 0 )
		for (size_t i=0; i<n/2; i++)
			(*files_left).push_back(((*files)[i]));
	// sinon on prend les (n+1)/2 premiers fichiers	
	else
		for (size_t i=0; i<(n+1)/2; i++)
			(*files_left).push_back(((*files)[i]));
	return *files_left;
}

// renvoie les fichiers a afficher a droite des repertoires
vector<File*> Folder::getRightFiles() {
	// n : le nombre de fichiers
	size_t n = (*files).size();
	vector<File*> *files_right;
	files_right = new vector<File*>;
	// si n est pair on prend les n/2 derniers fichiers	
	if ( n%2 == 0 )
		for (size_t i=n/2; i<n; i++)
			(*files_right).push_back(((*files)[i]));
	// sinon on prend les (n-1)/2 derniers fichiers
	else
		for (size_t i=(n+1)/2; i<n; i++)
			(*files_right).push_back(((*files)[i]));
	return *files_right;
}

// renvoie un vecteur de sous-repertoires ordonnés
// i.e. avec ceux de plus grande profondeur au milieu
vector<Folder*> Folder::getOrderedSubfolders() {
	// n : le nombre de sous-repertoires
	size_t n = (*subfolders).size();
	Folder *temp;
	temp = NULL;
	// copie du vecteur de sous-rep dans un autre vecteur
	vector<Folder*> *sub_ord;
	sub_ord = new vector<Folder*>;
	for (size_t i=0; i<n; i++)
		(*sub_ord).push_back((*subfolders)[i]);
	// on organise d'abord les repertoires de la plus petite à la plus grande prof
	// (algo du tri bulle)
	for (size_t i=0; i<n; i++)
		for (size_t j=0; j<n; j++)
			if (((*sub_ord)[i])->getProfMax() < ((*sub_ord)[j])->getProfMax())
			{
				temp = ((*sub_ord)[j]);
				((*sub_ord)[j]) = ((*sub_ord)[i]);
				((*sub_ord)[i]) = temp;
			}
	// il reste à réorganiser les rep avec ceux de plus grande prof au milieu du vecteur	
	// on cree un autre vecteur temporaire vide
	vector<Folder*> *sub_ord2;
	sub_ord2 = new vector<Folder*>;
	// auquel on ajoute n elements nuls
	(*sub_ord2).assign(n,temp);
	// on reorganise
	size_t j=0;
	for (size_t i=0; i<n; i++)
	{
		if (i%2 == 0)
			((*sub_ord2)[j]) = ((*sub_ord)[i]);
		else
		{
			((*sub_ord2)[n-(j+1)]) = ((*sub_ord)[i]);
			j++;
		}
	}	
	return *sub_ord2;
} 

Folder::~Folder() {
	for (size_t i=0; i<files->size(); i++)
		if (&(files[i]) != NULL)
			delete &(files[i]);
	for (size_t i=0; i<subfolders->size(); i++)
		if (&(subfolders[i]) != NULL)
			delete &(subfolders[i]);
}
